package com.bone.common.util;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.po.TableFill;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;

import java.util.ArrayList;
import java.util.List;

/**
 * @author : WangKeKe
 * @date : 2020/8/2 8:01
 * Description : 代码生成工具
 */

public class CodeGenerator {

    /**
     * MYSQL数据库连接
     */
    private static final String DATABASE_DRIVER = "com.mysql.cj.jdbc.Driver";
    private static final String DATABASE_URL = "jdbc:mysql://localhost:3306/bone?useUnicode=true&serverTimezone=UTC&characterEncoding=UTF-8";
    private static final String DATABASE_USERNAME = "root";
    private static final String DATABASE_PASSWORD = "123456";

    /**
     * 生成文件放入位置
     * // 当前项目的该目录下
     * System.getProperty("user.dir") + "/src/main/java";
     */
    private static final String OUT_PUT_DIR = "D:\\aboutOtherItem";
    private static final String FILE_PARENT = "com.bone.modules";

    private static final String AUTHOR = "王可可";


    public static void main(String[] args) {
        codeFactory("sys_quartz_job", "sys_", "quartz");
    }

    /**
     * 代码生成
     * - 如果数据库中存在以下两个字段
     * 1) deleted 逻辑删除 如果加入该字段 当前数据不会被真的删除 所有mp自带的方法都会在SQL后面拼接 AND deleted = 0
     * 2) version 乐观锁 更新操作需要带入该字段 这样就可以实现锁的机制
     * 3) createTime 自动填充 数据插入时 会加入时间
     * 4) updateTime 自动填充 数据更新时 会加入时间
     *
     * @param tableName            数据库表名
     * @param splitTableNamePrefix 需要剥离的表面前缀
     * @param moduleName           模块名称
     */
    private static void codeFactory(String tableName, String splitTableNamePrefix, String moduleName) {
        // 创建自动代码生成器
        AutoGenerator autoGenerator = new AutoGenerator();
        // 1.全局配置
        GlobalConfig globalConfig = new GlobalConfig();
        // 将代码生成到指定路径 当前项目路径
        globalConfig.setOutputDir(OUT_PUT_DIR);
        // 添加作者标识
        globalConfig.setAuthor(AUTHOR);
        // 是否打开资源管理器，就是等于生成后是否打开文件夹
        globalConfig.setOpen(false);
        // 是否覆盖原来的
        globalConfig.setFileOverride(false);
        // 通过正则表达式 去掉service的I前缀
        //globalConfig.setServiceName("%sService");
        // 设定ID的生成策略  雪花算法
        globalConfig.setIdType(IdType.AUTO);
        // 设定日期类型
        globalConfig.setDateType(DateType.ONLY_DATE);
        // 配置Swagger文档
        globalConfig.setSwagger2(true);


        globalConfig.setBaseResultMap(true);
        globalConfig.setBaseColumnList(true);

        // 2.设置数据源
        DataSourceConfig dataSourceConfig = new DataSourceConfig();
        dataSourceConfig.setDriverName(DATABASE_DRIVER);
        dataSourceConfig.setUrl(DATABASE_URL);
        dataSourceConfig.setUsername(DATABASE_USERNAME);
        dataSourceConfig.setPassword(DATABASE_PASSWORD);
        dataSourceConfig.setDbType(DbType.MYSQL);


        // 3.包的配置 -- 该配置会在当前项目的com.wkk.blog下生成Controller,Service,mapper,entity
        PackageConfig packageConfig = new PackageConfig();
        packageConfig.setModuleName(moduleName);
        packageConfig.setParent(FILE_PARENT);


        autoGenerator.setTemplateEngine(new FreemarkerTemplateEngine());
        // 配置自定义输出模板
        TemplateConfig templateConfig = new TemplateConfig();
        templateConfig
                .setController("codeTemplate/controller/controller.java")
                .setEntity("codeTemplate/entity/entity.java")
                .setMapper("codeTemplate/mapper/mapper.java")
                .setXml("codeTemplate/mapper/xml/mapper.xml")
                .setService("codeTemplate/service/service.java")
                .setServiceImpl("codeTemplate/service/impl/serviceImpl.java");

        autoGenerator.setTemplate(templateConfig);


        // 4.策略配置
        StrategyConfig strategy = new StrategyConfig();
        // 设置要映射的表名
        strategy.setInclude(tableName);
        // 生成的文件去掉表名前缀
        strategy.setTablePrefix(splitTableNamePrefix);
        // 选择实体类名字的生成策略
        strategy.setNaming(NamingStrategy.underline_to_camel);
        strategy.setColumnNaming(NamingStrategy.underline_to_camel);
        // 使用lombok注解
        strategy.setEntityLombokModel(true);
        strategy.setEntitySerialVersionUID(true);

        // 使用RestController注解
        strategy.setRestControllerStyle(true);
        // 逻辑删除策略配置
        strategy.setLogicDeleteFieldName("deleted");
        // 自动填充策略配置
        TableFill createTime = new TableFill("create_time", FieldFill.INSERT);
        TableFill createBy = new TableFill("create_by", FieldFill.INSERT);
        TableFill updateTime = new TableFill("update_time", FieldFill.INSERT_UPDATE);
        TableFill updateBy = new TableFill("update_By", FieldFill.INSERT_UPDATE);
        List<TableFill> fills = new ArrayList<>(4);
        fills.add(createTime);
        fills.add(createBy);
        fills.add(updateTime);
        fills.add(updateBy);
        strategy.setTableFillList(fills);
        // 乐观锁字段配置
        strategy.setVersionFieldName("version");
        // 逻辑删除字段配置
        strategy.setLogicDeleteFieldName("deleted");


        autoGenerator.setGlobalConfig(globalConfig);
        autoGenerator.setDataSource(dataSourceConfig);
        autoGenerator.setPackageInfo(packageConfig);
        autoGenerator.setStrategy(strategy);
        //执行
        autoGenerator.execute();
    }
}
